using System;
using System.Collections;
using System.Text;
using System.Xml;

namespace PacSnake
{
	/// <summary>
	/// LevelSet inherits from LevelSetInfo. Now we add a collection of levels.
	/// </summary>
	public class LevelSet : LevelSetInfo
	{
        // Collection of the levels in a XML level set
        private ArrayList levels = new ArrayList();

        
        /// <summary>
        /// Load all levels from the XML
        /// </summary>
        /// <param name="levelSetFilename">Level set filename</param>
        public void LoadLevels(string levelSetFilename)
        {
            // Deletes current levels
            levels.Clear();
            
            XmlDocument doc = new XmlDocument();
            doc.Load(levelSetFilename);
            
            // Get all Level elements from the level set
            XmlNodeList levelInfoList = doc.SelectNodes("//Level");
            
            int levelNr = 1;
            foreach (XmlNode levelInfo in levelInfoList)
            {
                // Add level to the level collection
                levels.Add(ReadLevelNodes(levelInfo));
                levelNr++;
            }
        }
        
        
        /// <summary>
        /// Read the level line by line from the XML
        /// </summary>
        /// <param name="levelInfo">XmlNode with a 'level line'</param>
        /// <returns>A Level object</returns>
        private Level ReadLevelNodes(XmlNode levelInfo)
        {
            // Read the attributes from the level element            
            XmlAttributeCollection xac = levelInfo.Attributes;
            string levelName = xac["Id"].Value;
            int levelWidth = int.Parse(xac["Width"].Value);
            int levelHeight = int.Parse(xac["Height"].Value);
            int levelSpeed = int.Parse(xac["Speed"].Value);
            
            // Read the layout of the level
            XmlNodeList levelLayout = levelInfo.SelectNodes("L");
            
            // Declare the level map
            StringBuilder sb = new StringBuilder();
            
            // Read the level line by line from the XML
            for (int i = 0; i < levelHeight; i++)
                sb.Append(levelLayout[i].InnerText);
            
            // Return new level.
            return new Level(levelName, sb.ToString(), levelWidth,
                levelHeight, levelSpeed);
        }
        
        
        /// <summary>
        /// Writes the last finished level to the level set. If we've already
        /// finished the level set, then there's no need to update the level.
        /// </summary>
        /// <param name="levelNr">Level number we just finished</param>
        public void SetLevelFinished(int levelNr)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(filename);
            
            XmlNode nodeLevel = doc.SelectSingleNode("//LastFinishedLevel");
            if (int.Parse(nodeLevel.InnerText) != nrOfLevelsInSet)
                nodeLevel.InnerText = levelNr.ToString();
            
            doc.Save(filename);
        }
        
        
        /// <summary>
        /// Indexer
        /// </summary>
        /// <exception cref="System.ArgumentOutOfRangeException">Throws an
        /// exception when an invalid index is passed to the indexer. An index
        /// is invalid when it's negative, or greater than the size of the
        /// collection</exception>
        public Level this[int index]
        {
            get
            {
                if (index < 0 || index >= levels.Count)
                    throw new ArgumentOutOfRangeException("index",
                        "Index was negatief of groter dan het aantal levels " +
                        "in de collection.");
                
                return (Level)levels[index];
            }
        }
	}
}
